#include "HandleCollisions.h"
#include "Circle.h"
#include "CRectangle.h"

void HandleCollisions::handleCircleCircleCollision (Circle * circ1 , Circle * circ2)
{
	int dir = 0;
	bool collisionX = false, collisionY = false;
	Point colPoint;

	// checking outside collision
	if (getCircToCircOutsideColPoint(*circ1, *circ2 , colPoint))
	{
		//colPoint = getCircToCircColPoint(circ1, circ2);
		dir = checkCollisionX(*circ1 , colPoint);
		if (dir == 2)
		{
			collisionY = true;
			collisionX = true;
		}
		else if (dir == 1)
			collisionX = true;
		else
			collisionY = true;
		updateDir(*circ1 , *circ2 , collisionX , collisionY, collisionX, collisionY);

	}
	else if ((!(collisionX || collisionY)) && (circ1->getRadius() != circ2->getRadius()))
	{
		if (getCircToCircInsideColPoint(*circ1, *circ2 , colPoint))
		{
			dir = checkCollisionX(*circ1 , colPoint);
			if (dir == 2)
			{
				collisionY = true;
				collisionX = true;
			}
			else if (dir == 1)
				collisionX = true;
			else
				collisionY = true;
			updateDir(*circ1 , *circ2 , collisionX , collisionY, collisionX, collisionY);
	
		}
	}
}

void HandleCollisions::handleCircleRectangleCollision (Circle * circ1 , CRectangle * rec2)
{
	handleRectangleCircleCollision (rec2 , circ1);
}

void HandleCollisions::handleRectangleCircleCollision (CRectangle * rec1 , Circle * circ2)
{
	int dir;
	bool circ2CollisionX, circ2CollisionY , rec1CollisionX , rec1CollisionY;

	isRecCollideWithCir (rec1, circ2, dir, circ2CollisionX, circ2CollisionY,  rec1CollisionX,  rec1CollisionY);

	if (dir == 0)
	{
		int shapeToMove = whichShapeHasBiggerDir (rec1->getDirX(), rec1->getDirY());

		// move it

		if (shapeToMove == 1)
		{
			rec1->subtractSumDirX ();
			rec1->subtractSumDirY ();
		}
		else
		{
			circ2->subtractSumDirX ();
			circ2->subtractSumDirY ();
		}

		// check again...
		isRecCollideWithCir (rec1, circ2, dir, circ2CollisionX, circ2CollisionY,  rec1CollisionX,  rec1CollisionY);

		if (dir == 0)
		{
			// move back!
			if (shapeToMove == 1)
			{
				rec1->addSumDirX ();
				rec1->addSumDirY ();
			}
			else
			{
				circ2->addSumDirX ();
				circ2->addSumDirY ();
			}
		}
	}
	if (dir != 0)
	{
		updateDir(*rec1 , *circ2 , rec1CollisionX , rec1CollisionY , circ2CollisionX , circ2CollisionY);
	}
}

int HandleCollisions::whichShapeHasBiggerDir (const double& shape1DirX, const double& shape1DirY)
{
	if (shape1DirX != 0 || shape1DirY != 0)
	{
		return 1;
	}

	return 2;
}

void HandleCollisions::isRecCollideWithCir (CRectangle * rec1 , Circle * circ2, int& dir, bool& circ2CollisionX,
	bool& circ2CollisionY , bool& rec1CollisionX , bool& rec1CollisionY)
{
	dir = 0;
	circ2CollisionX = circ2CollisionY = rec1CollisionX = rec1CollisionY = false;

	Point colPoint;

	if (isRecOnCircle( *rec1 , *circ2, colPoint))
	{
		dir = checkCircCollisionX(*circ2 , colPoint);
		if (dir == 2)
		{
			circ2CollisionY = true;
			circ2CollisionX = true;
		}
		else if (dir == 1)
			circ2CollisionX = true;
		else
			circ2CollisionY = true;
		// if collision has occured at this point - the collision point must be one of the rectangle's corners.
		rec1CollisionY = rec1CollisionX = true;
	}
	else 
	{
		dir = isCircOnRec( *circ2 , *rec1 );
		if (dir)
		{
			if (dir == 1)
				rec1CollisionX = circ2CollisionX =  true;
			else if (dir == 2 ) 
				rec1CollisionY = circ2CollisionY = true;
		}
	}
}


void HandleCollisions::handleRectangleRectangleCollision (CRectangle * rec1 , CRectangle * rec2)
{
	int dir = 0;
	bool collisionX, collisionY;
	collisionX = collisionY = false;

	Point rec1UL((int)(rec1->getXPoint() + rec1->getSumDirX()),
				 (int)(rec1->getYPoint() + rec1->getSumDirY())),
		  rec1DR(rec1UL.getx() + rec1->getWidth()-1, rec1UL.gety() + rec1->getHeight()-1);

	Point rec2UL((int)(rec2->getXPoint() + rec2->getSumDirX()), 
				 (int)(rec2->getYPoint() + rec2->getSumDirY())), 
		  rec2DR((int)(rec2UL.getx() + rec2->getWidth()-1), (int)(rec2UL.gety() + rec2->getHeight()-1));

	// The normal collision check - checks if in the next step the recs will collide
	checkRecToRecCollision (rec1UL, rec1DR, rec2UL, rec2DR, collisionX, collisionY);

	// This is a special check - if both of the recs move in opposite directions and they
	//	are, on the x axis or on the y, overlap,
	//  one of them should stay where it is and the other should take one step back
	if (!collisionX || !collisionY)
	{
		if (checkIfRecStuckInRec(rec1, rec2))
		{
			if (whichShapeToDelay(rec1->getDirX(), rec1->getDirY(),	collisionX, collisionY) == 1)
			{
				rec1->subtractSumDirX();
				rec1->subtractSumDirY();
				rec1UL.set ((int)(rec1->getXPoint() + rec1->getSumDirX()),
							(int)(rec1->getYPoint() + rec1->getSumDirY()));
				rec1DR.set (rec1UL.getx() + rec1->getWidth()-1, rec1UL.gety() + rec1->getHeight()-1);
			}
			else
			{
				rec2->subtractSumDirX();
				rec2->subtractSumDirY();
				rec2UL.set ((int)(rec2->getXPoint() + rec2->getSumDirX()),
							(int)(rec2->getYPoint() + rec2->getSumDirY()));
				rec2DR.set (rec2UL.getx() + rec2->getWidth()-1, rec2UL.gety() + rec2->getHeight()-1);
			}

			collisionX = collisionY = 0;
			HandleCollisions::checkRecToRecCollision (rec1UL, rec1DR, rec2UL, rec2DR, collisionX, collisionY);
		}
	}

	if (collisionX || collisionY)
	{
		updateDir(*rec1 , *rec2, collisionX, collisionY , collisionX , collisionY);
	}



}

int HandleCollisions::whichShapeToDelay (const double& shape1DirX, const double& shape1DirY,
								 const bool& collisionX, const bool& collisionY) 
{
	// The Shape that we want to delay, is the one that has 0 on the collision axis. 
	if (collisionX)
	{
		return (shape1DirX == 0 ? 1 : 2);
	}
	else if (collisionY)
	{
		return (shape1DirY == 0 ? 1 : 2);
	}

	return 1;
}

void HandleCollisions::checkRecToRecCollision (const Point& rec1UL,const  Point& rec1DR,const  Point& rec2UL, const Point& rec2DR,
								 bool& collisionX,  bool& collisionY) 
{
	// only if there is a collision on X axis or Y axis it returns the true value to the returned bool
	int rec1XL = rec1UL.getx(), 
		rec1XR = rec1DR.getx(), 
		rec2XL = rec2UL.getx(), 
		rec2XR = rec2DR.getx();

	int rec1YU = rec1UL.gety(), 
		rec1YD = rec1DR.gety(), 
		rec2YU = rec2UL.gety(), 
		rec2YD = rec2DR.gety();

	if ((	rec1XL == rec2XR
		|| rec1XL == rec2XL
		|| rec1XR == rec2XL
		|| rec1XR == rec2XR) || 
		( (abs(rec1XL - rec2XR) == 1)
		|| (abs(rec1XL - rec2XL) == 1)
		|| (abs(rec1XR - rec2XR) == 1)
		|| (abs(rec1XR - rec2XL) == 1)))

	{
		if (checkRecToRecCollisionX (rec1YU, rec1YD, rec2YU, rec2YD))
		{
			collisionX = true;
		}
	}

	if ((   rec1YU == rec2YU
		|| rec1YU == rec2YD
		|| rec1YD == rec2YU
		|| rec1YD == rec2YD)|| 
		( (abs(rec1YU - rec2YU) == 1)
		|| (abs(rec1YU - rec2YD) == 1)
		|| (abs(rec1YD - rec2YU) == 1)
		|| (abs(rec1YD - rec2YD) == 1)))
	{
		if (checkRecToRecCollisionY (rec1XL, rec1XR, rec2XL, rec2XR))
		{
			collisionY = true;
		}
	}
}


bool HandleCollisions::checkRecToRecCollisionX ( const int& rec1YU, const int& rec1YD, const int& rec2YU, const int& rec2YD) 
{
	if (   rec1YU >= rec2YU
		&& rec1YU <= rec2YD)
		return true;

	if (   rec1YD >= rec2YU
		&& rec1YD <= rec2YD)
		return true;

	if (   rec2YU >= rec1YU
		&& rec2YU <= rec1YD)
		return true;

	if (   rec2YD >= rec1YU
		&& rec2YD <= rec1YD)
		return true;

	return false;
}

bool HandleCollisions::checkRecToRecCollisionY ( const int& rec1XL,const  int& rec1XR,const  int& rec2XL,const  int& rec2XR) 
{
	if (   rec1XL >= rec2XL
		&& rec1XL <= rec2XR)
		return true;

	if (   rec1XR >= rec2XL
		&& rec1XR <= rec2XR)
		return true;

	if (   rec2XL >= rec1XL
		&& rec2XL <= rec1XR)
		return true;

	if (   rec2XR >= rec1XL
		&& rec2XR <= rec1XR)
		return true;

	return false;
}

bool HandleCollisions::checkIfRecStuckInRec (const CRectangle * rec1 , const CRectangle * rec2) 
{
	// Creating 4 points from the two recs
	Point rec1UL((int)(rec1->getXPoint() + rec1->getSumDirX()) , (int)(rec1->getYPoint() + rec1->getSumDirY())),
		  rec1UR(rec1UL.getx() + rec1->getWidth()-1, rec1UL.gety()),
		  rec1DL(rec1UL.getx(), rec1UL.gety() + rec1->getHeight()-1),
		  rec1DR(rec1UL.getx() + rec1->getWidth()-1, rec1UL.gety() + rec1->getHeight()-1);

	Point rec2UL((int)(rec2->getXPoint() + rec2->getSumDirX()), (int)(rec2->getYPoint() + rec2->getSumDirY())),
		  rec2UR((rec2UL.getx() + rec2->getWidth()-1), (rec2UL.gety())),
		  rec2DL(rec2UL.getx(), (int)(rec2UL.gety() + (rec2->getHeight()-1))),
		  rec2DR(rec2UL.getx() + rec2->getWidth()-1, rec2UL.gety() + rec2->getHeight()-1);
	
	// If the first rec is part inside the second one,
	// or if the second one is part inside the first one - 
	// cancel animation
	if (rec1PartInRec2 (rec1UL, rec1UR, rec1DL, rec1DR, rec2UL, rec2DR) ||
		rec1PartInRec2 (rec2UL, rec2UR, rec2DL, rec2DR, rec1UL, rec1DR))
	{
		return true;
	}
	return false;
}

bool HandleCollisions::rec1PartInRec2 (const  Point& rec1UL, const  Point& rec1UR, const  Point& rec1DL,const Point& rec1DR,
					const   Point& rec2UL,const   Point& rec2DR) 
{
	int counter = 0;
	int resOfULPoint, resOfURPoint, resOfDLPoint, resOfDRPoint;

	// If even one point is located on the border of the rec, 
	// then the rec is part in the other one
	if ((resOfULPoint = pointInsideRec (rec2UL, rec2DR, rec1UL)) == 2 ||
		(resOfURPoint = pointInsideRec (rec2UL, rec2DR, rec1UR)) == 2 ||
		(resOfDLPoint = pointInsideRec (rec2UL, rec2DR, rec1DL)) == 2 ||
		(resOfDRPoint = pointInsideRec (rec2UL, rec2DR, rec1DR)) == 2) 
		return true;

	// If the program reached this section, it means that none of the points
	// is on the border of the rec
	counter = resOfULPoint + resOfURPoint + resOfDLPoint + resOfDRPoint;

	// If the rec is totally inside or outside of the other rec
	if (counter == 4 || counter == 0)
		return false;

	return true;
}

int HandleCollisions::pointInsideRec (const  Point& rec1UL,const  Point& rec1DR,const  Point& point) 
{
	// If the point is entierly inside the rec - return 1
	if (point.getx() > rec1UL.getx() && 
		point.getx() < rec1DR.getx() &&
		point.gety() > rec1UL.gety() && 
		point.gety() < rec1DR.gety() )
		return 1;

	// If the point is touching one of the borders of the rec - return 2
	if (point.getx() >= rec1UL.getx() && 
		point.getx() <= rec1DR.getx() &&
		point.gety() >= rec1UL.gety() && 
		point.gety() <= rec1DR.gety() )
		return 2;

	// The point is outside the rec
	return 0;
}

int HandleCollisions::checkRecCollision(const CRectangle & rec1 , const Point & colPoint)
{
	// returns 0 for no collisions , 1 for axis x collision , 2 for axis y collision and 3 for both axis col.
	int col = 0;
	Point rec1UL((int)(rec1.getXPoint() + rec1.getSumDirX()),
				 (int)(rec1.getYPoint() + rec1.getSumDirY())),
		  rec1DR(rec1UL.getx() + rec1.getWidth()-1, rec1UL.gety() + rec1.getHeight()-1);
	int rec1XL = rec1UL.getx();
	int rec1XR = rec1DR.getx();
	int rec1YU = rec1UL.gety();
	int rec1YD = rec1DR.gety();

	int colPointX = colPoint.getx();
	int colPointY = colPoint.gety();

	if (((	rec1XL == colPointX ) && ( rec1YU <= colPointY) && (rec1YD >= colPointY)) || 
		((	rec1XR == colPointX ) && ( rec1YU <= colPointY) && (rec1YD >= colPointY)))
		col = 1;

	if (((	rec1YU == colPointY ) && ( rec1XL <= colPointX) && (rec1XR >= colPointX)) ||
			 ((	rec1YD == colPointY ) && ( rec1XL <= colPointX) && (rec1XR >= colPointX)))
	{
		if (col == 1 )
			col = 3;
		else 
			col = 2;

	}
	return col;
}

int HandleCollisions::isCircOnRec(const Circle & circ2 , const CRectangle & rec1 )
{
	// returns 0 for no collision , 1 for axis x collisions , 2 for axis y collision.
	int left , right , down , up;

	left = (int)(circ2.getSumDirX() + circ2.getXPoint() - circ2.getRadius() + circ2.getDirX());
	up = (int)(circ2.getSumDirY() + circ2.getYPoint() - circ2.getRadius() + circ2.getDirY());
	right = (int)(circ2.getSumDirX() +  circ2.getXPoint() + circ2.getRadius() + circ2.getDirX());
	down = (int)(circ2.getSumDirY() +  circ2.getYPoint() + circ2.getRadius() + circ2.getDirY());

	int centerX = (int)(circ2.getSumDirX() + circ2.getXPoint() + circ2.getDirX());
	int centerY = (int)(circ2.getSumDirY() +  circ2.getYPoint() + circ2.getDirY());

	if ((	checkRecCollision( rec1,  Point(left ,centerY))) 
		||	(checkRecCollision( rec1, Point(right ,centerY))))
		return 1;
	else if ((checkRecCollision( rec1,  Point(centerX ,up))) 
			|| (checkRecCollision( rec1,  Point(centerX ,down))))
	{
		return 2;
	}
	return 0;
}

int HandleCollisions::checkCircCollisionX(const Circle & circ , const Point & colPoint) 
{
	// returns 0 for no collision , 1 for collision and 2 for exact collision with x and y
	int x1 = int(circ.getPoint().getx() + circ.getSumDirX());
	//int y1 = int(this->getPoint().gety() + this->getSumDirY());
	int r = circ.getRadius();

	int left = x1 - int(floor(sqrt((r * r) / 2.0) + 0.5));
	int right = x1 + int(floor(sqrt((r * r) / 2.0) + 0.5));

	if (colPoint.getx() < left || colPoint.getx() > right)

		return 1;
	else if (colPoint.getx() == left || colPoint.getx() == right)
		return 2;
	else
		return 0;
	
}

bool HandleCollisions::isRecOnCircle(const CRectangle & rec1 ,const Circle & circ2 , Point & colPoint)
{
	int x1 = int(circ2.getXPoint() + circ2.getSumDirX());
	int y1 = int(circ2.getYPoint() + circ2.getSumDirY());
	int r = circ2.getRadius();

	Point rec1UL((int)(rec1.getXPoint() + rec1.getSumDirX() + rec1.getDirX()) , (int)(rec1.getYPoint() + rec1.getSumDirY() + rec1.getDirY())),
		  rec1UR(rec1UL.getx() + rec1.getWidth()-1, rec1UL.gety()),
		  rec1DL(rec1UL.getx(), rec1UL.gety() + rec1.getHeight()-1),
		  rec1DR(rec1UL.getx() + rec1.getWidth()-1, rec1UL.gety() + rec1.getHeight()-1);

	if  (getCircRecColPoint (x1 , y1 , rec1UL.getx() , rec1UL.gety() , r , colPoint ))
		return true;
	else if (getCircRecColPoint (x1 , y1 , rec1UR.getx() , rec1UR.gety() , r , colPoint))
		return true;
	else if (getCircRecColPoint (x1 , y1 , rec1DL.getx() , rec1DL.gety() , r , colPoint))
		return true;
	else if (getCircRecColPoint (x1 , y1 , rec1DR.getx() , rec1DR.gety() , r , colPoint))
		return true;
	else 
		return false;
}

bool HandleCollisions::getCircRecColPoint (int x1 ,int y1 ,int x2 , int  y2 , int radius , Point & colPoint )
{

	int d = int(sqrt(double((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))));

	if (d == radius )
	{
		colPoint = Point(x2 , y2);
		return true;
	}
	return false;
}

void HandleCollisions::updateDir( Shape &shape1 , Shape &shape2 , bool shape1ColX, bool shape1ColY 
										, bool shape2ColX , bool shape2ColY)
{
	double shape1DirX = 0 , shape1DirY = 0;
	double shape2DirX = 0 , shape2DirY = 0;
	int timesshape1ChangedDirX = shape1.getTimesDirXChanged ();
	int timesshape1ChangedDirY = shape1.getTimesDirYChanged ();
	int timesshape2ChangedDirX = shape2.getTimesDirXChanged ();
	int timesshape2ChangedDirY = shape2.getTimesDirYChanged ();

	if (shape1ColX)
		shape1DirX = shape1.getDirX();
	if (shape1ColY)
		shape1DirY = shape1.getDirY();
	if (shape2ColX)
		shape2DirX = shape2.getDirX();
	if (shape2ColY)
		shape2DirY = shape2.getDirY();

	if (!shape2ColX && !shape1ColY && !shape2ColX && !shape2ColY)
	{
		return;
	}
	else if (shape1ColY || shape2ColY)
	{
		if ((shape1DirY < 0 && shape2DirY > 0) || (shape1DirY > 0 && shape2DirY < 0) )
		{
			if (timesshape1ChangedDirY == 0)
			{
				shape1DirY *= -1;
				shape1.add1TimeDirYChanged();
			}

			if (timesshape2ChangedDirY == 0)
			{
				shape2DirY *= -1;
				shape2.add1TimeDirYChanged();
			}
		}
		else
		{
			if (abs(shape1DirY) > abs(shape2DirY))
			{
				if (timesshape1ChangedDirY == 0)
				{
					shape1DirY *= -1;
					shape1.add1TimeDirYChanged();
				}
			}
			else
			{
				if (timesshape2ChangedDirY == 0)
				{
					shape2DirY *= -1;
					shape2.add1TimeDirYChanged();
				}
			}
		}
	}


	if (shape1ColX || shape2ColX)
	{
		if ((shape1DirX < 0 && shape2DirX > 0) || (shape1DirX > 0 && shape2DirX < 0))
		{
			if (timesshape1ChangedDirX == 0)
			{
				shape1DirX *= -1;
				shape1.add1TimeDirXChanged();
			}

			if (timesshape2ChangedDirX == 0)
			{
				shape2DirX *= -1;
				shape2.add1TimeDirXChanged();
			}
		}
		else
		{
			if (abs(shape1DirX) > abs(shape2DirX))
			{
				if (timesshape1ChangedDirX == 0)
				{
					shape1DirX *= -1;
					shape1.add1TimeDirXChanged();
				}
			}
			else
			{
				if (timesshape2ChangedDirX == 0)
				{
					shape2DirX *= -1;
					shape2.add1TimeDirXChanged();
				}
			}

		}
	}

	if (!shape1ColX)
		shape1DirX = shape1.getDirX();
	if (!shape1ColY)
		shape1DirY = shape1.getDirY();
	if (!shape2ColX)
		shape2DirX = shape2.getDirX();
	if (!shape2ColY)
		shape2DirY = shape2.getDirY();

	shape1.setDirection(shape1DirX, shape1DirY);
	shape2.setDirection(shape2DirX, shape2DirY);

}

bool HandleCollisions::isCircleToCircleOverlap(const Circle &circ1 , const Circle &circ2) 
{
	int x1 = int(circ1.getPoint().getx() + circ1.getSumDirX());
	int y1 = int(circ1.getPoint().gety() + circ1.getSumDirY());
	int x2 = int(circ2.getPoint().getx() + circ2.getSumDirX());
	int y2 = int(circ2.getPoint().gety() + circ2.getSumDirY());
	int r1 = circ1.getRadius();
	int r2 = circ2.getRadius();

	int d = int(sqrt(double(((x1 - x2)*(x1 - x2)) + ((y1 - y2)*(y1 - y2)))));

	if (d > (r1 - r2) && (d < (r1 + r2)))
		return true;
	else
		return false;

}

bool HandleCollisions::getCircToCircOutsideColPoint(const Circle &circ1 ,const Circle &circ2 , Point & colPoint)
{
	//determing and calculating the outside collision point between the two circles.
	int x1 = int(circ1.getPoint().getx() + circ1.getSumDirX()); //+ circ1.getDirX());
	int y1 = int(circ1.getPoint().gety() + circ1.getSumDirY()) ;//+ circ1.getDirY());
	int x2 = int(circ2.getPoint().getx() + circ2.getSumDirX()); //+ circ1.getDirX());
	int y2 = int(circ2.getPoint().gety() + circ2.getSumDirY()) ;//+ circ1.getDirY());
	int r1 = circ1.getRadius();
	int r2 = circ2.getRadius();

	colPoint.set((x1*r2+x2*r1)/(r1+r2) , (y1*r2+y2*r1)/(r1+r2));

	if (pointOnCirc(circ1 , colPoint) && pointOnCirc(circ2 , colPoint))
		return true;
	else
		return false;

}

bool HandleCollisions::getCircToCircInsideColPoint(const Circle &circ1 ,const Circle &circ2 , Point & colPoint)
{
	//determing and calculating the Inside collision point between the two circles.
	int x1 = int(circ1.getPoint().getx() + circ1.getSumDirX());
	int y1 = int(circ1.getPoint().gety() + circ1.getSumDirY());
	int x2 = int(circ2.getPoint().getx() + circ2.getSumDirX());
	int y2 = int(circ2.getPoint().gety() + circ2.getSumDirY());
	int r1 = circ1.getRadius();
	int r2 = circ2.getRadius();

	colPoint.set(abs(x1*r2-x2*r1)/abs(r1-r2) , abs(y1*r2-y2*r1)/abs(r1-r2));
	if (pointOnCirc(circ1 , colPoint) || pointOnCirc(circ2 , colPoint))
		return true;
	else
		return false;

}

bool HandleCollisions::pointOnCirc (const Circle & circ1 ,const Point & p )
{

	int x1 = int(circ1.getPoint().getx() + circ1.getSumDirX());
	int y1 = int(circ1.getPoint().gety() + circ1.getSumDirY());
	int r1 = circ1.getRadius();
	int x2 = p.getx();
	int y2 = p.gety();

	int d = int(sqrt(double((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))));

	return (d == r1);

}

bool HandleCollisions::pointOnCircNext (const Circle & circ1 ,const Point & p )
{

	int x1 = int(circ1.getPoint().getx() + circ1.getSumDirX() + circ1.getDirX());
	int y1 = int(circ1.getPoint().gety() + circ1.getSumDirY() + circ1.getDirY());
	int r1 = circ1.getRadius() +1 ;
	int x2 = p.getx();
	int y2 = p.gety();

	int d = int(sqrt(double((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2))));

	return (d == r1);

}

int HandleCollisions::checkCollisionX(const Circle & circ1 , const Point & colPoint) 
{
	// returns 0 for no collision , 1 for collision and 2 for exact collision with x and y
	int x1 = int(circ1.getPoint().getx() + circ1.getSumDirX());
	int r = circ1.getRadius();

	int left = x1 - int(floor(sqrt((r * r) / 2.0) + 0.5));
	int right = x1 + int(floor(sqrt((r * r) / 2.0) + 0.5));

	if (colPoint.getx() < left || colPoint.getx() > right)

		return 1;
	else if (colPoint.getx() == left || colPoint.getx() == right)
		return 2;
	else
		return 0;
	
}

bool HandleCollisions::checkRecStuck (const CRectangle & rec1 , const MyScreen & scr) 
{
	int x1, y1, maxHeight, maxWidth;

	x1 = rec1.getXPoint();
	y1 = rec1.getYPoint();
	maxWidth = x1 + rec1.getWidth() -1;
	maxHeight = y1 + rec1.getHeight() -1;


	for ( unsigned int i=0; i < rec1.getHeight(); ++i)
	{
		if (Point::checkIfPointOnScr(Point (x1, y1+i), scr))
			return true;
		if (Point::checkIfPointOnScr(Point (maxWidth, y1+i), scr))
			return true;
		
	}

	for ( unsigned int i=0; i < rec1.getWidth(); ++i)
	{
		if (Point::checkIfPointOnScr(Point (x1+i, y1), scr))
			return true;
		if (Point::checkIfPointOnScr(Point (x1+i, maxHeight), scr))
			return true;
	}
	return false;

}

bool HandleCollisions::checkCircStuck (const Circle & circ1 , const MyScreen & scr)
{
	int x, y ,r;
	int modFactorX = MAX_SCREEN_X-1, modFactorY = MAX_SCREEN_Y-1;
	double currX, currY;

	x = circ1.getXPoint();
	y = circ1.getYPoint();
	r = circ1.getRadius();
	

	for( int i = 0; i <= 90; i += PRECISION )
	{
		// Calculates the value that is needed to be added to the original center point
		currX = (cos( (double)i ) * r);
		currY = (sin( (double)i ) * r);

		if (check4Points(x , y , currX, currY , scr))
		{
			return true;
		}
		
	}

	return false;
}

bool HandleCollisions::check4Points (double x, double y, double currXAxis, double currYAxis, const MyScreen & scr)
{
	int printXLeft, printXRight, printYUpper, printYLower; 
	double xLeft, xRight, yUpper, yLower;

	currXAxis = abs(currXAxis);
	currYAxis = abs(currYAxis);

	// calculating the x left value
	xLeft = x - currXAxis;
	printXLeft = (int)(floor (xLeft + 0.5 ));

	// calculating the x right value
	xRight = x + currXAxis;
	printXRight = (int)(floor (xRight + 0.5 ));
	
	// calculating the y upper value
	yUpper = y - currYAxis;
	printYUpper = (int)(floor (yUpper + 0.5 ));

	// calculating the y lower value
	yLower = y + currYAxis;
	printYLower = (int)(floor (yLower + 0.5 ));

	if (Point::checkIfPointOnScr(Point (printXRight, printYLower), scr))
			return true;
	else if (Point::checkIfPointOnScr(Point (printXLeft, printYLower), scr))
			return true;
	else if (Point::checkIfPointOnScr(Point (printXRight, printYUpper), scr))
			return true;
	else if (Point::checkIfPointOnScr(Point (printXLeft, printYUpper), scr))
			return true;
	else 
		return false;
}